package com.example.javaproject.design;


/**
 * <p>
 * 状态模式
 * 状态模式与策略模式结构几乎一致，但本质和含义完全不一样。状态模式的行为是平行的，不可替代的。但是策略模式中行为是可以相互替代的
 * <p>
 * 使用场景：
 * 1、一个对象的行为是取决于 它处于的状态
 * 2、代码中包含大量 与对象状态有关的语句
 * <p>
 * 例子：电视遥控器
 * <p>
 * <p/>
 */
public class StateDesignTest {

    public static void main(String[] args) {

        // 普通设计版
        TvController controller = new TvController();
        controller.powerOn();
        controller.nextChannel();
        controller.powerOff();
        controller.turnUp();

        // 状态模式设计版
        TvControllerNew controllerNew = new TvControllerNew();
        controllerNew.powerOn();
        controllerNew.nextChannel();
        controllerNew.powerOff();
        controllerNew.turnUp();

    }
}


/**
 * 电视遥控器实现
 * <p>
 * 里面有2个状态，当前执行 调频道调音量时会判断 电视机状态；这里只有2种状态，当状态更加多比如5种状态时，这个代码将会变得难以维护
 */
class TvController {

    // 开机状态
    private final static int POWER_ON = 1;
    // 关机状态
    private final static int POWER_OFF = 2;

    // 电视机当前状态
    private int mState = POWER_OFF;

    public void powerOn() {
        mState = POWER_ON;
        System.out.println("开机啦");
    }

    public void powerOff() {
        mState = POWER_OFF;
        System.out.println("关机啦");
    }

    /**
     * 频道的+,-
     */
    public void nextChannel() {
        if (mState == POWER_ON) {
            System.out.println("调整电视频道");
        } else {
            System.out.println("当前电视机没有开机，开机后才能调整电视频道");
        }
    }

    /**
     * 音量+,-
     */
    public void turnUp() {
        if (mState == POWER_ON) {
            System.out.println("调整电视音量");
        } else {
            System.out.println("当前电视机没有开机, 开机后才能调整音量");
        }
    }
}


/**
 * 抽离电视机状态，在不同状态下，点击按钮会出现不同效果
 */
interface TvState {
    void nextChannel();

    void turnUp();
}

/**
 * 开机状态
 */
class PowerOnState implements TvState {

    @Override
    public void nextChannel() {
        System.out.println("调整电视频道");
    }

    @Override
    public void turnUp() {
        System.out.println("调整电视音量");
    }
}

/**
 * 关机状态
 */
class PowerOffState implements TvState {
    @Override
    public void nextChannel() {
        System.out.println("当前电视机没有开机，开机后才能调整电视频道");
    }

    @Override
    public void turnUp() {
        System.out.println("当前电视机没有开机, 开机后才能调整音量");
    }
}

/**
 *  电视机操作接口
 */
interface TvPowerController {
    void powerOn();
    void powerOff();
}

/**
 * 电视机遥控器实现
 *
 *  这里的实现，将电视机状态抽离成接口，不同状态下，相同行为出现不同的结果。避免调了各种状态判断
 */
class TvControllerNew implements TvPowerController {

    // 默认情况下 电视机是关机的
    private TvState mState = new PowerOffState();

    @Override
    public void powerOn() {
        mState = new PowerOnState();
    }

    @Override
    public void powerOff() {
        mState = new PowerOffState();
    }

    public void nextChannel() {
        mState.nextChannel();
    }

    public void turnUp() {
        mState.turnUp();
    }
}
